/**
 * @title 智能合约整合演示脚本
 * @description 一站式演示ERC20和NFT合约的部署与交互
 * 此脚本结合了部署和交互的完整流程，方便用户一键运行查看效果
 */
async function main() {
  /**
   * 第一部分：部署合约
   */
  console.log("=== 智能合约演示流程 ===");
  console.log("1. 部署合约");
  
  /**
   * 获取账户列表
   * ethers.getSigners() 返回Hardhat环境中的账户列表
   * owner: 部署者账户（默认使用第一个账户）
   * addr1: 第一个测试账户（用于接收ERC20转账）
   * addr2: 第二个测试账户（用于接收NFT转移）
   */
  const [owner, addr1, addr2] = await ethers.getSigners();
  console.log(`使用账户: ${owner.address}`);
  
  /**
   * 获取合约工厂
   * ethers.getContractFactory() 创建合约工厂实例
   * 每个工厂用于部署对应的合约类型
   */
  const SimpleERC20 = await ethers.getContractFactory("SimpleERC20");
  const SimpleNFT = await ethers.getContractFactory("SimpleNFT");
  
  console.log("部署合约中...");
  
  /**
   * 部署ERC20合约
   * 参数1000000 是初始供应量（不包含精度）
   * deploy() 返回一个Promise，解析为合约实例
   * deployed() 等待合约部署交易被确认
   */
  const erc20Token = await SimpleERC20.deploy(1000000);
  await erc20Token.deployed();
  console.log(`ERC20代币已部署到: ${erc20Token.address}`);
  
  /**
   * 部署NFT合约
   * 参数1: NFT集合名称
   * 参数2: NFT集合符号
   * 参数3: NFT元数据基础URI
   */
  const nftContract = await SimpleNFT.deploy("MyNFT", "MNFT", "https://example.com/nfts/");
  await nftContract.deployed();
  console.log(`NFT合约已部署到: ${nftContract.address}`);
  
  /**
   * 第二部分：合约交互演示
   */
  console.log("\n=== 2. 合约交互演示 ===");
  
  /**
   * ERC20合约交互演示
   * 演示查询信息、余额查询和转账功能
   */
  console.log("\n=== ERC20合约交互演示 ===");
  
  // 查询代币基本信息
  const name = await erc20Token.name();
  const symbol = await erc20Token.symbol();
  const decimals = await erc20Token.decimals();
  const totalSupply = await erc20Token.totalSupply();
  
  console.log(`代币名称: ${name}`);
  console.log(`代币符号: ${symbol}`);
  console.log(`代币精度: ${decimals}`);
  
  /**
   * 格式化显示总供应量
   * ethers.utils.formatUnits() 将包含精度的大数值转换为可读格式
   * 参数1: 包含精度的大数值
   * 参数2: 精度位数
   */
  console.log(`总供应量: ${ethers.utils.formatUnits(totalSupply, decimals)} ${symbol}`);
  
  // 查询部署者的余额
  const ownerBalance = await erc20Token.balanceOf(owner.address);
  console.log(`部署者余额: ${ethers.utils.formatUnits(ownerBalance, decimals)} ${symbol}`);
  
  // 转账演示
  /**
   * 准备转账金额
   * ethers.utils.parseUnits() 将可读数值转换为包含精度的大数值
   */
  const transferAmount = ethers.utils.parseUnits("100", decimals);
  console.log(`\n向 ${addr1.address} 转账 ${ethers.utils.formatUnits(transferAmount, decimals)} ${symbol}`);
  
  // 执行转账
  const tx = await erc20Token.transfer(addr1.address, transferAmount);
  console.log(`交易哈希: ${tx.hash}`);
  // 等待交易确认
  await tx.wait();
  
  // 查询转账后的余额
  const newOwnerBalance = await erc20Token.balanceOf(owner.address);
  const addr1Balance = await erc20Token.balanceOf(addr1.address);
  
  console.log(`转账后部署者余额: ${ethers.utils.formatUnits(newOwnerBalance, decimals)} ${symbol}`);
  console.log(`接收者余额: ${ethers.utils.formatUnits(addr1Balance, decimals)} ${symbol}`);
  
  /**
   * NFT合约交互演示
   * 演示铸造NFT、查询NFT信息和转移NFT功能
   */
  console.log("\n=== NFT合约交互演示 ===");
  
  // 查询NFT集合信息
  const nftName = await nftContract.name();
  const nftSymbol = await nftContract.symbol();
  
  console.log(`NFT名称: ${nftName}`);
  console.log(`NFT符号: ${nftSymbol}`);
  
  // 铸造新的NFT
  console.log(`\n向 ${owner.address} 铸造一个NFT`);
  const mintTx = await nftContract.mintNFT(owner.address);
  console.log(`铸造交易哈希: ${mintTx.hash}`);
  // 等待铸造交易确认并获取交易收据
  const receipt = await mintTx.wait();
  
  // 从交易事件中提取铸造的NFT ID
  /**
   * 交易收据(receipt)包含了交易触发的所有事件
   * 铸造NFT时会触发Transfer事件，其中包含铸造的NFT ID
   */
  let tokenId = null;
  for (const event of receipt.events) {
    if (event.event === "Transfer") {
      tokenId = event.args.tokenId.toString();
      break;
    }
  }
  
  console.log(`铸造的NFT ID: ${tokenId}`);
  
  // 查询NFT的拥有者
  const ownerOfToken = await nftContract.ownerOf(tokenId);
  console.log(`NFT ${tokenId} 的拥有者: ${ownerOfToken}`);
  
  // 查询NFT的URI（元数据链接）
  const tokenURI = await nftContract.tokenURI(tokenId);
  console.log(`NFT ${tokenId} 的URI: ${tokenURI}`);
  
  // 转移NFT演示
  console.log(`\n将NFT ${tokenId} 转移给 ${addr2.address}`);
  const transferNFTTx = await nftContract.transferFrom(owner.address, addr2.address, tokenId);
  console.log(`转移交易哈希: ${transferNFTTx.hash}`);
  // 等待转移交易确认
  await transferNFTTx.wait();
  
  // 查询转移后的NFT拥有者
  const newOwnerOfToken = await nftContract.ownerOf(tokenId);
  console.log(`转移后NFT ${tokenId} 的拥有者: ${newOwnerOfToken}`);
  
  console.log("\n=== 演示完成 ===");
  
  console.log("\n\n=== DeFi借贷池演示 ===");
  console.log("要查看DeFi借贷池功能演示，请运行以下命令：");
  console.log("  npx hardhat run scripts/defi_demo.js");
  console.log("\nDeFi借贷池功能包括：");
  console.log("  1. 存款赚取利息 - 用户存入资产获得aToken");
  console.log("  2. 添加抵押 - 使用aToken作为抵押品");
  console.log("  3. 借款功能 - 基于抵押品借入资产");
  console.log("  4. 还款功能 - 偿还借款");
  console.log("  5. 移除抵押和提款");
  console.log("\n详细演示请运行专用脚本！");
}

// 执行主函数
main()
  .then(() => process.exit(0)) // 成功时正常退出
  .catch((error) => {
    console.error("演示过程中发生错误:", error); // 捕获并显示错误
    process.exit(1); // 出错时退出，返回非零状态码
  });